# -*- coding: utf-8 -*-
import requests
from write_log import write_log
from apscheduler.schedulers.background import BackgroundScheduler
import time

rpa_url = 'http://localhost:8700'
SID = "bcdefghijklmnopqrstuvwxyz{23456789:101"
api_url = "http://192.168.77.5:10801/rpa/sql/run"


from datetime import datetime

def update_time(original_time_str):
    # 原始时间字符串
    # original_time_str = "20241117-145242"

    # 解析原始时间字符串为 datetime 对象
    # 注意：这里的格式字符串 "%Y%m%d-%H%M%S" 与原始时间字符串匹配
    dt = datetime.strptime(original_time_str, "%Y%m%d-%H%M%S")

    # 将 datetime 对象格式化为新的时间字符串
    # 注意：这里的格式字符串 "%Y-%m-%d %H:%M:%S" 是目标格式
    formatted_time_str = dt.strftime("%Y-%m-%d %H:%M:%S")

    return formatted_time_str  # 输出: 2024-11-17 14:52:42


# 获取主机名称
def get_local_ip():
    import socket
    # 获取当前系统主机名
    hostname = socket.gethostname()
    # 获取主机名对应的IP地址
    local_ip = socket.gethostbyname(hostname)
    # print(local_ip)
    return local_ip


# 查询，获取返回
def post_select_api(data):
    # data = {'sid':SID, 'sql_lang': 'select * from flow_info'}
    headers = {'Content-Type': 'application/json'}
    res = requests.post(api_url, json=data, headers=headers)
    if res.status_code == 200:
        return res.json()
    else:
        return False


# print(post_select_api(''))


# 增删改语句，不需要返回
def post_insert_api(data):
    headers = {'Content-Type': 'application/json'}
    res = requests.post(api_url, json=data, headers=headers)
    if res.status_code != 200:
        return False
    return res.json()


#异步执行流程，参数：mrpaid
def start_async_flow(mrpaid):
    headers = {'Content-Type': 'application/json'}
    res = requests.post(rpa_url + '/executor/run/async/' + mrpaid, headers=headers)
    # print(res.json())
    if res.json()['error_code'] == 0:
        return res.json()['workflow_id']
    else:
        return False



# 停止流程，参数workid
def stop_flow(workid):
    headers = {'Content-Type': 'application/json'}
    res = requests.post(rpa_url + '/executor/stop/' + workid, headers=headers)
    # print(res.json())
    if res.json()['error_code'] == 0:
        return True
    else:
        return False


#暂停执行流程
def pause_flow(workid):
    headers = {'Content-Type': 'application/json'}
    res = requests.post(rpa_url + '/executor/pause/' + workid, headers=headers)
    # print(res.json())
    if res.json()['error_code'] == 0:
        return True
    else:
        return False


# 继续执行流程
def continue_flow(workid):
    headers = {'Content-Type': 'application/json'}
    res = requests.post(rpa_url + '/executor/continue/' + workid, headers=headers)
    # print(res.json())
    if res.json()['error_code'] == 0:
        return True
    else:
        return False


# 获取流程信息，检查是否需要插入
def get_local_flow():
    postval = post_select_api({'sid': SID, 'sql_lang': 'select * from flow_info'})
    if postval:
        headers = {'Content-Type': 'application/json'}
        res = requests.get(rpa_url + '/mrpa/list', headers=headers)
        # print(res.text)
        ip = get_local_ip()
        if res.status_code != 200:
            write_log('调用弘玑接口获取流程信息失败', log_level='ERROR')
        else:
            if postval['status'] == 0:
                pwa_flow_list = [cell[0] for cell in postval['data']]
                for i in res.json()['mrpa_file_list']:
                    if i['mrpa_id'] not in pwa_flow_list:
                        # print('*' * 20)
                        # print(cyclone['mrpa_id'])
                            oneinfo = (i['mrpa_id'], ip, i['mrpa_id'], i['file_name'], i['file_path'], i['file_md5'])
                            sql = f"INSERT INTO flow_info (id, robot_id, mrpa_id, flow_name, file_path, file_md5) VALUES {oneinfo}"
                            post_insert_api({'sid': SID, 'sql_lang': sql})
            elif postval['status'] == 1:
                for i in res.json()['mrpa_file_list']:
                    oneinfo = (i['mrpa_id'], ip, i['mrpa_id'], i['file_name'], i['file_path'], i['file_md5'])
                    sql = f"INSERT INTO flow_info (id, robot_id, mrpa_id, flow_name, file_path, file_md5) VALUES {oneinfo}"
                    post_insert_api({'sid': SID, 'sql_lang': sql})
            else:
                write_log(f'调用接口获取流程信息异常：{postval}', log_level='ERROR')
    else:
        write_log('调用接口获取流程信息数据失败', log_level='ERROR')


def get_process_history(worker_id):
    headers = {'Content-Type': 'application/json'}
    res = requests.get(rpa_url + '/executor/history?detailed=true', headers=headers)
    if res.status_code != 200:
        return False
    else:
        for i in res.json()['detailedhistorys']:
            if i['workflowId'] == worker_id:
                workend_time = update_time(i['endTime'])
                # print(workend_time)
                return [i['type'], workend_time]


# 待执行分为，已停止，发起执行
def examine_flow():
    postval = post_select_api({'sid': SID, 'sql_lang': 'select * from flow_history'})

    if postval['status'] == 0:
        for flow in postval['data']:
            # print(flow)
            # continue
            if flow[9] == '待执行':
                if flow[8] == '发起执行':
                    id = flow[0]
                    rpa_id = flow[1]
                    # print(id)
                    # print(rpa_id)
                    # 先去更新流程表，正在执行
                    sql = f"UPDATE flow_info SET status='执行中' WHERE mrpa_id='{rpa_id}'"
                    data = {'sid': SID, 'sql_lang': sql}
                    postval = post_insert_api(data)
                    if postval:
                        if postval['status'] == 2:
                            write_log(f'写入flow_info表，status状态失败: {sql}', log_level='ERROR')
                    else:
                        write_log('更新flow_info表，status状态失败', log_level='ERROR')
                    # 执行异步开启流程
                    rpaval = start_async_flow(rpa_id)
                    if rpaval:
                        history = get_process_history(rpaval)
                        if history[0] != 'pre-execute':
                            sql = f"UPDATE flow_history SET status = '执行失败', workflowid = '{rpaval}', stop_time = '{history[1]}', grouping = '执行结束', message = '{history[0]}' WHERE id = '{id}'"
                        else:
                            sql = f"UPDATE flow_history SET status = '执行成功', workflowid = '{rpaval}', stop_time = '{history[1]}', grouping = '执行结束', message = '{history[0]}' WHERE id = '{id}'"
                        data = {'sid': SID, 'sql_lang': sql}
                        # print(sql)
                        postval = post_insert_api(data)
                        if postval:
                            if postval['status'] == 2:
                                write_log(f'写入流程执行历史库失败: {sql}', log_level='ERROR')
                        else:
                            write_log('插入流程执行信息表失败', log_level='ERROR')
                    else:
                        write_log('调用弘玑机器人执行异步流程失败', log_level='ERROR')
                    # 刷新流程表为空闲中
                    sql = f"UPDATE flow_info SET status='空闲中' WHERE mrpa_id='{rpa_id}'"
                    data = {'sid': SID, 'sql_lang': sql}
                    postval = post_insert_api(data)
                    if postval:
                        if postval['status'] == 2:
                            write_log(f'写入flow_info表，status状态失败: {sql}', log_level='ERROR')
                    else:
                        write_log('更新flow_info表，status状态失败', log_level='ERROR')

                elif flow[8] == '已停止':
                    workflow_id = flow[-1]
                    stopval = stop_flow(workflow_id)
                    if not stopval:
                        id = flow[0]
                        sql = f"UPDATE flow_history SET status = '停止失败' WHERE id = '{id}'"
                        data = {'sid': SID, 'sql_lang': sql}
                        # print(sql)
                        postval = post_insert_api(data)
                        if postval:
                            if postval['status'] == 2:
                                write_log(f'写入流程执行历史库失败-停止流程: {sql}', log_level='ERROR')
                        else:
                            write_log('插入流程执行信息表失败-停止流程', log_level='ERROR')
    elif postval['status'] == 1:
        write_log('流程执行信息表为空')
    else:
        write_log(f'调用接口获取流程执行历史表失败: {postval}', log_level='ERROR')


# 获取机器人健康状态
def robot_health():
    headers = {'Content-Type': 'application/json'}
    res = requests.get(rpa_url + '/executor/healthcheck', headers=headers)
    if res.status_code != 200:
        write_log('请求弘玑机器人健康状态接口失败', log_level='ERROR')
    else:
        # res.json()['error_code']
        data = {'sid': SID, 'sql_lang': 'SELECT * FROM robot_info'}
        robotval = post_select_api(data)
        ip = get_local_ip()
        # print(robotval)
        robotlist = [robotip[1] for robotip in robotval['data']]
        # print(robotlist)
        sql = ''
        if robotval['status'] == 0:
            if ip in robotlist:
                sql = f"UPDATE robot_info SET health = '{robotval['status']}' WHERE ip = '{ip}'"
            else:
                value = (ip, robotval['status'])
                sql = f"INSERT INTO robot_info (ip, health) VALUES {value}"
        elif robotval['status'] == 1:
            value = (ip, robotval['status'])
            sql = f"INSERT INTO robot_info (ip, health) VALUES {value}"
        else:
            write_log(f'查询机器人信息表失败：{robotval}', log_level='ERROR')
        if sql:
            data = {'sid': SID, 'sql_lang': sql}
            robotval = post_insert_api(data)
            if robotval:
                if robotval['status'] == 2:
                    write_log(f'修改机器人信息数据库失败: {sql}', log_level='ERROR')
            else:
                write_log(f'修改机器人信息数据库失败', log_level='ERROR')


if __name__ == '__main__':
    # 创建调度器实例
    scheduler = BackgroundScheduler()

    # get_local_flow()
    # examine_flow()
    # robot_health()

    # 添加任务
    scheduler.add_job(get_local_flow, 'interval', seconds=10)
    scheduler.add_job(examine_flow, 'interval', seconds=2)
    scheduler.add_job(robot_health, 'interval', seconds=5)


    # 启动调度器
    scheduler.start()

    try:
        # 保持主线程运行，以便调度器可以继续执行任务
        while True:
            time.sleep(1)
    except (KeyboardInterrupt, SystemExit):
        # 当主线程被终止时，关闭调度器
        scheduler.shutdown()
        # print()
